package com.photoeditor.demo.ui.widget.image.magazine;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.RectF;
import android.graphics.Xfermode;
import android.os.Handler;
import android.os.Looper;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AnimationUtils;
import android.view.animation.Transformation;
import android.widget.RelativeLayout;

import com.common.base.ComponentContext;
import com.photoeditor.R;
import com.photoeditor.demo.model.image.collage.util.CollageGestureRecognizer;
import com.photoeditor.demo.model.image.tools.MatrixAnimation;
import com.photoeditor.demo.model.image.util.ImageHelper;
import com.photoeditor.demo.ui.activity.edit.EditorImageActivity;
import com.photoeditor.demo.ui.widget.collage.BorderView;


/**
 * @dest 拼接的子View
 */

public class EditMagazineChildRectfView extends View implements CollageGestureRecognizer.Listener {
    /**
     * 变形动画的持续时间（毫秒）
     */
    private static final long DURATION_MATRIX_ANIMATION = 150L;
    public RectF mDefaultRect;
    private Paint mSrcPaint;
    private Paint mDstPaint;
    private static final Xfermode srcmode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
    private Bitmap mSourceBitmap;
    private Matrix mSupportMatrix;
    private RectF mDefaultDisplayRect;
    private boolean mIsInit = false;
    public Bitmap mScaleRegineBitmap;
    private Matrix mCacheMatrix;
    private Matrix mRotationMatrix;
    private Matrix mOppMatrix;
    private Matrix mTranslateMatrix;
    private Matrix mDrawMatrix;
    private RectF mDisplayRect;
    private RectF outsideRect;
    private boolean mIsInChange = false;
    private boolean mIsAnimationRunning = false;
    private boolean mIsTouch = false;
    private boolean mIsScale = false;
    private Paint mBorderPaint;
    private MatrixAnimation mMatrixAnimation = null;
    private Transformation mTransformation = null;
    //    合成图片源低图
    private Bitmap mSrcRegineBitmap;

    private final static int BORDER_WIDTH = ComponentContext.getContext().getResources().getDimensionPixelSize(R.dimen.image_magazinecollage_border_width);
    private EditorImageActivity mActivity;
    private final static int MSG_REFRESH = 1;
    Handler mHandler = new Handler(Looper.getMainLooper()) {
        public void handleMessage(android.os.Message msg) {
            if (msg.what == MSG_REFRESH) {
                invalidate();
                //控制显示的边界
                BorderView tag = (BorderView) getTag();
                EditMagazineCollageRelativeLayout parent = (EditMagazineCollageRelativeLayout) getParent();
                tag.setVisibility(mIsTouch ? VISIBLE : GONE);
                //必须做非空判断，当快速切换模板时，加载时进行手势操作，parent为null;
                if (parent != null) {
                    parent.removeView(tag);
                    parent.addView(tag, mLp);
                }
            }
        }

        ;
    };
    private RelativeLayout.LayoutParams mLp;

    public EditMagazineChildRectfView(Context context, RectF currentRect, RectF outsideRect) {
        super(context);
        mDefaultRect = currentRect;
        init();
        this.outsideRect = outsideRect;
    }


    private void init() {
        mActivity = (EditorImageActivity) getContext();

        mSrcPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mSrcPaint.setXfermode(srcmode);
        mDstPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mDstPaint.setStyle(Paint.Style.FILL);
        mBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mBorderPaint.setStyle(Paint.Style.STROKE);
        mBorderPaint.setColor(getResources().getColor(R.color.accent_color));
        mBorderPaint.setStrokeWidth(BORDER_WIDTH);

        mSupportMatrix = new Matrix();
        mRotationMatrix = new Matrix();
        mOppMatrix = new Matrix();
        mTranslateMatrix = new Matrix();
        mDisplayRect = new RectF();
        mCacheMatrix = new Matrix();
        mDrawMatrix = new Matrix();

        mDefaultDisplayRect = new RectF();
        //边界参数控制
        mLp = new RelativeLayout.LayoutParams((int) (mDefaultRect.width() + 0.5), (int) (mDefaultRect.height() + 0.5));
        mLp.topMargin = (int) (mDefaultRect.top + 0.5);
        mLp.leftMargin = (int) (mDefaultRect.left + 0.5);

    }

    /**
     * 计算当前的Draw Matrix,缓存matrix,避免一次改变matrix都创建matrix
     *
     * @return
     */
    public Matrix countDrawMatrix() {
        mCacheMatrix.reset();
        mCacheMatrix.set(mSupportMatrix);
        mCacheMatrix.postConcat(mRotationMatrix);
        mCacheMatrix.postConcat(mOppMatrix);
        mCacheMatrix.postConcat(mTranslateMatrix);
        return mCacheMatrix;
    }

    /**
     * 重置所有的矩阵
     */
    public void reset() {
        mSupportMatrix.reset();
        mRotationMatrix.reset();
        mCacheMatrix.reset();
        mOppMatrix.reset();
        mDrawMatrix.reset();
        mTranslateMatrix.reset();
    }

    /**
     * 设置Draw Matrix 并刷新
     */
    public void setDrawMatrix(Matrix matrix) {
        mDrawMatrix.set(matrix);
        refresh();
    }

    public Bitmap getSrcRegineBitmap() {
        return mSrcRegineBitmap;
    }

    /**
     * 获取Draw matrix
     */
    public Matrix getDrawMatrix() {
        return new Matrix(mDrawMatrix);
    }

    public boolean isInChange() {
        return mIsInChange;
    }

    /**
     * 获取当前的源图片
     */
    public Bitmap getSourceBitmap() {
        return mSourceBitmap;
    }

    public boolean isTouch() {
        return mIsTouch;
    }

    /**
     * 获取当前Bitmap 的绘制Rect
     */
    public RectF getDisplayRect(Matrix matrix) {
        if (null != mSourceBitmap) {
            mDisplayRect.set(0, 0, mSourceBitmap.getWidth(),
                    mSourceBitmap.getHeight());
            matrix.mapRect(mDisplayRect);
            return mDisplayRect;
        } else {
            mDisplayRect.set(0, 0, 0, 0);
        }
        return mDisplayRect;
    }

    /**
     * 设置源图片
     */
    public void setSourceBitmap(Bitmap bitmap, int resId) {
        mSourceBitmap = bitmap;
        if (mSourceBitmap != null && !mSourceBitmap.isRecycled()) {
            if (mSrcRegineBitmap == null) {
                mSrcRegineBitmap = BitmapFactory.decodeResource(getResources(), resId);
                if (mScaleRegineBitmap == null) {
                    //缩放低图
                    mScaleRegineBitmap = ImageHelper.getScaleBitmap(mDefaultRect, mSrcRegineBitmap);
                }
            }
            reset();
            resetSupportMatrix();
            setDrawMatrix(countDrawMatrix());
        } else {
            setIsInit(false);
            reset();
        }

    }

    public void setSourceBitmap(Bitmap bitmap) {
        mSourceBitmap = bitmap;
        if (mSourceBitmap != null && !mSourceBitmap.isRecycled()) {
            setIsInit(true);
            reset();
            resetSupportMatrix();
            setDrawMatrix(countDrawMatrix());
        } else {
            setIsInit(false);
            reset();
        }
    }

    /**
     * 用于设置是否初始化
     */
    public void setIsInit(boolean isInit) {
        mIsInit = isInit;
    }

    //初始化绘制图片matrix,缩放图片,使得图片能铺满rectf
    private void resetSupportMatrix() {
        mSupportMatrix.reset();
        float bw = mSourceBitmap.getWidth();
        float bh = mSourceBitmap.getHeight();

        float viewW = mDefaultRect.width();
        float viewH = mDefaultRect.height();

        float w, h;
        float scale;
        float translateX, translateY;
        if (bw / bh >= viewW / viewH) {//比较宽  这时候应高顶着高  才不会显示底图
            w = bw * viewH / bh;//真实显示高度/原图的高度*原图的宽度=需要显示的宽度
            scale = w / bw;
            translateX = (viewW - w) / 2;
            translateY = 0.0f;
        } else {
            w = viewW;
            h = bh * viewW / bw;
            scale = w / bw;
            translateX = 0.0f;
            translateY = (viewH - h) / 2;
        }
        mSupportMatrix.postScale(scale, scale, 0, 0);
        mSupportMatrix.postTranslate(translateX, translateY);
        mDefaultDisplayRect.set(0, 0, bw, bh);
        //把坐标位置放入矩阵
        mSupportMatrix.mapRect(mDefaultDisplayRect);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int count = canvas.saveLayer(0.0f, 0.0f, getWidth(), getHeight(),
                null, Canvas.ALL_SAVE_FLAG);
        if (!mIsInChange) {
            canvas.drawBitmap(mScaleRegineBitmap, 0, 0, mDstPaint);
            //没选中是对图片滑动
            if (mMatrixAnimation != null && !mMatrixAnimation.hasEnded()) {
                // 如果动画还没结束，则获取当前变换过程的矩阵
                mMatrixAnimation.getTransformation(
                        AnimationUtils.currentAnimationTimeMillis(),
                        mTransformation);
                Matrix currMatrix = mTransformation.getMatrix();

                if (currMatrix.equals(getDrawMatrix())) {
                    // 如果矩阵没有变化，可能是时间值间隔太短或动画刚刚开始，这时手动重绘
                    invalidate();
                } else {
                    // 设置当前的矩阵变换，设置后会重绘
                    setDrawMatrix(mTransformation.getMatrix());
                }
            } else {
                // 动画已经结束播放了，重新修改状态值
                mIsAnimationRunning = false;
            }
            canvas.drawBitmap(mSourceBitmap, getDrawMatrix(), mSrcPaint);
        }
        canvas.restoreToCount(count);
    }

    public boolean isInit() {
        return mIsInit;
    }

    /**
     * 使用动画模式设置矩阵对象，并实现平滑变换。设置后动画随即开始
     *
     * @param matrix 需要变换的目标矩阵对象
     */
    public void setAnimationImageMatrix(Matrix matrix) {
        if (!mIsInChange) {
            mIsAnimationRunning = true;

            if (mTransformation == null) {
                mTransformation = new Transformation();
            }

            if (mMatrixAnimation == null) {
                mMatrixAnimation = new MatrixAnimation(getDrawMatrix(), matrix);
                mMatrixAnimation.setDuration(DURATION_MATRIX_ANIMATION);
            }

            mMatrixAnimation.setFromMatrix(getDrawMatrix());
            mMatrixAnimation.setToMatrix(matrix);
            mMatrixAnimation.start();
            refresh();
        } else {
            setDrawMatrix(matrix);
        }
    }

    /**
     * 设置是否选中
     */
    public void setIsTouch(boolean istouch) {
        if (mIsTouch != istouch) {
            mIsTouch = istouch;
            refresh();
        }

    }

    //刷新界面显示
    public void refresh() {
        if (!mHandler.hasMessages(MSG_REFRESH)) {
            mHandler.sendEmptyMessage(MSG_REFRESH);
        }
    }

    @Override
    public boolean onSingleTapUp(float x, float y) {
        return true;
    }

    @Override
    public boolean onSingleTapComfirm(float x, float y) {
        if (!mIsInit) return false;
        return true;
    }

    @Override
    public boolean onDoubleTap(float x, float y) {
        return false;
    }

    @Override
    public boolean onScroll(float x, float y, float dx, float dy, float totalX, float totalY) {
        if (!mIsScale) {
            float translateX = -dx;
            float translateY = -dy;


            mOppMatrix.postTranslate(translateX, translateY);
            setDrawMatrix(countDrawMatrix());
        }
        return true;
    }

    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        if (!mIsInit) return false;
        return true;
    }

    @Override
    public boolean onScaleBegin(float focusX, float focusY) {
        mIsScale = true;
        return true;
    }

    @Override
    public boolean onScale(float focusX, float focusY, float scale) {
        if (Float.isNaN(scale) || Float.isInfinite(scale)) return false;

        Matrix drawMatrix = countDrawMatrix();
        RectF rect = getDisplayRect(drawMatrix);
        if (rect.width() * scale < getWidth() || rect.height() * scale < getHeight()) {
            drawMatrix.postScale(scale, scale, getWidth() / 2, getHeight() / 2);
            rect = getDisplayRect(drawMatrix);
            mOppMatrix.postScale(scale, scale, getWidth() / 2, getHeight() / 2);
            ensureRect(rect, null);
        } else {
            drawMatrix.postScale(scale, scale, focusX, focusY);
            rect = getDisplayRect(drawMatrix);
            mOppMatrix.postScale(scale, scale, focusX, focusY);
            ensureRect(rect, null);
        }
        setDrawMatrix(countDrawMatrix());
        return true;
    }

    /**
     * 计算合适的偏移量  当前显示Rect大于View的宽高时  保证不出边界
     * 当前显示Rect小于View的宽高时  保证居中
     *
     * @param matrix 传入Matrix的话就会对Matrix执行
     */
    private void ensureRect(RectF rectF, Matrix matrix) {
        RectF mViewCacheRect = new RectF();
        float width = mDefaultRect.width();
        float height = mDefaultRect.height();
        float dx = 0, dy = 0;
        if (rectF.height() > height) {//对上下边的处理
            if (rectF.top > 0f) {
                dy = -rectF.top;
            } else if (rectF.bottom < height) {
                dy = height - rectF.bottom;
            }
        } else {//高度比View高度小  需要居中
            mViewCacheRect.set(0, 0, width, height);
            dy = (mViewCacheRect.height() - rectF.height()) / 2 + mViewCacheRect.top - rectF.top;
        }
        if (rectF.width() > width) {//对左右边的处理
            if (rectF.left > 0f) {
                dx = -rectF.left;
            } else if (rectF.right < width) {
                dx = width - rectF.right;
            }
        } else {//宽度比View高度小  需要居中
            mViewCacheRect.set(0, 0, width, height);
            dx = (mViewCacheRect.width() - rectF.width()) / 2 + mViewCacheRect.left - rectF.left;
        }
        if (matrix == null) {
            mOppMatrix.postTranslate(dx, dy);
        } else {
            matrix.postTranslate(dx, dy);
        }
    }

    @Override
    public void onScaleEnd() {
        mIsScale = false;
    }

    @Override
    public boolean onRotaionBegin() {
        return false;
    }

    @Override
    public boolean onRotaion(float delta) {
        return false;
    }

    @Override
    public void onRotaionEnd() {

    }

    @Override
    public void onDown(float x, float y) {
        if (!mIsInit) return;
        mIsScale = false;
    }

    @Override
    public void onUp(float x, float y) {
        mIsScale = false;
        RectF displayRect = getDisplayRect(countDrawMatrix());
        //判断需不需要复原
        if (displayRect.width() < getWidth() || displayRect.height() < getHeight()
                || displayRect.left > 0f || displayRect.right < getWidth()
                || displayRect.top > 0f || displayRect.bottom < getHeight()) {
            //前面的子view四舍五入过,所以要减1
            if (displayRect.width() < getWidth() - 1 || displayRect.height() < getHeight() - 1) {//宽或者高比需要显示的小 需要复原
                mOppMatrix.reset();
                mTranslateMatrix.reset();
                setAnimationImageMatrix(countDrawMatrix());
            } else {//不需要复原只需要平移到合适位置
                if (displayRect.left > 0) {//左边
                    mOppMatrix.postTranslate(-displayRect.left, 0);
                }

                if (displayRect.top > 0) {
                    mOppMatrix.postTranslate(0, -displayRect.top);
                }

                if (displayRect.right < getWidth()) {
                    mOppMatrix.postTranslate(getWidth() - displayRect.right, 0);
                }

                if (displayRect.bottom < getHeight()) {
                    mOppMatrix.postTranslate(0, getHeight() - displayRect.bottom);
                }
                setAnimationImageMatrix(countDrawMatrix());
            }
        }
    }

    @Override
    public void onLongPress(float x, float y) {

    }
}